home *** CD-ROM | disk | FTP | other *** search
- /* C* input qualification routines.
-
- source: in.c
- started: October 26, 1985
- version:
- February 22, 1989
-
- PUBLIC DOMAIN SOFTWARE
-
- The CSTAR program was placed in the public domain on June 15, 1991,
- by its author and sole owner,
-
- Edward K. Ream
- 1617 Monroe Street
- Madison, WI 53711
- (608) 257-0802
-
- CSTAR may be used for any commercial or non-commercial purpose.
-
- See cstar.h or cstar.c for a DISCLAIMER OF WARRANTIES.
- */
- #include "cstar.h"
-
- /*
- Declare routines of this file.
- */
- bool is_reserved (register char * name, int length);
- struct x_ex * x_exists (struct node *q);
-
- static bool am_match(register int mode, register struct node * loc);
- static bool is_mpc (register struct node *p);
- static bool is_m0 (register struct node *p);
- static bool is_m1 (register struct node *p);
- static bool is_m2 (register struct node *p);
- static bool is_m3 (register struct node *p);
- static bool is_m4 (register struct node *p);
- static bool is_m5 (register struct node *p);
- static bool is_m6 (register struct node *p);
- static bool is_m70 (register struct node *p);
- static bool is_m71 (register struct node *p);
- static bool is_m72 (register struct node *p);
- static bool is_m73 (register struct node *p);
- static bool is_m74 (register struct node *p);
-
- /*
- Declare existence table defined in t2.s.
- */
- extern int * x_lookup[];
-
- /*
- Declare the reserved word index table which are defined in t1.s
- The dimension 2 is just a dummy value.
- */
- #ifdef DRI
- extern char * rwx_tab [2];
- #else
- extern struct t1_tab_struct * rwx_tab [2];
- #endif
-
- /*
- Use the tables in t1.s to see if name[] contains a reserved word.
- If so, set t_type, t_subtype and return TRUE.
- Otherwise, set t_type to NULL and return FALSE.
- */
- bool
- is_reserved(register char * name, int length)
- {
- #ifdef DRI
- register byte * p;
- register char c;
- #else
- char c;
- register struct t1_tab_struct * p;
- register struct t1_entry_struct * e;
- register int i, n;
- int t;
- #endif
-
- TRACEP("is_reserved", printf("(%s, %d)\n", name, length));
-
- c = *name;
- if (c == '\0') {
- goto not_found;
- }
-
- #ifdef DRI
- /* Fetch the pointer. */
- p = rwx_tab [c - 'A'];
-
-
- /* Search for the proper subtable. */
- for (;;) {
-
- TRACEP("is_reserved", printf("rwx_tab subtable: p = %p\n", p));
-
- if (p == NULL) {
- goto not_found;
- }
-
- if (*(int *)p > length) {
- goto not_found;
- }
- else if (length == *(int *)p) {
- break;
- }
- else {
- /* Point at the address of the next subtable. */
- p += 2;
-
- /* Fetch the address of the next subtable. */
- p = * (char **) p;
- }
- }
-
- TRACEP("is_reserved", printf("subtable found: p = %p\n", p));
-
- while (*p != '\0') {
-
- TRACEP("is_reserved", printf("compare: %s, %s\n", name, p));
- TRACEP("is_reserved", printf("note: length = %d\n", length, p));
-
- if(str_eq(name, p)) {
-
- /* Found. */
- p += length + 1;
- t_type = (int) *p++;
- t_subtype = (int) *p;
- t_type &= 0xff;
- t_subtype &= 0xff;
-
- TRACEP("is_reserved",
- printf("return %d, %d\n", t_type, t_subtype));
-
- return TRUE;
- }
- /* Skip over the entry. */
- p += length + 3;
-
- TRACEP("is_reserved", printf("skip to: p = %p\n", p));
- }
-
- #else
-
- /* Search for the proper subtable. */
- for (p = rwx_tab [c - 'A']; ; p++) {
-
- TRACEP("is_reserved", printf("p = %p\n", p));
-
- if (p == NULL) {
- goto not_found;
- }
-
- TRACEP("is_reserved", printf("p -> t_strlen = %d\n",
- p -> t_strlen));
-
- if (p == NULL || p -> t_strlen > length) {
- goto not_found;
- }
- else if (p -> t_strlen == length) {
- break;
- }
- }
-
- /* A subtable with the right length has been found. */
- n = p -> t_entries;
- for (i = 0, e = p -> t_entry; i < n; e++, i++) {
-
- TRACEP("is_reserved",
- printf("compare: %s, %s\n", name, e -> e_string));
-
- t = strcmp(name, e -> e_string);
- if (t == 0) {
-
- /* Found. */
- t_type = ((int) (e -> e_arg1)) & 0xff;
- t_subtype = ((int) (e -> e_arg2)) & 0xff;
-
- TRACEP("is_reserved",
- printf("return %d, %d\n", t_type, t_subtype));
-
- return TRUE;
- }
- /* -----
- else if (t > 0) {
- goto not_found;
- }
- ----- */
- }
- #endif
-
- not_found:
- t_type = 0;
- t_subtype = 0;
-
- TRACEP("is_reserved_ret", printf("ISR: returns 0\n"));
- return FALSE;
- }
-
-
- /*
- Use the tables in t2.s to determine whether a particular
- operator operand combination exists
-
- Return a pointer to a static structure containing various
- results of the operation, including an operation
- length to attach to the code node, a machine code, etc.
-
- Return NULL if not found.
-
- Op is the desired X_TOK, and arg1 and arg2 the arguments, if any.
- */
- struct x_ex *
- x_exists(struct node *q)
- {
- register struct node * arg1, * arg2;
- register unsigned int val;
- register int *p;
- int op, l1, l2;
- static struct x_ex x;
-
- TRACEP("x_exists", printf("(%d, %p, %p)\n", op, arg1, arg2));
-
- op = q -> n_xtype;
- arg1 = q -> n_arg1;
- arg2 = q -> n_arg2;
- for (p = x_lookup[op]; p[0] >= 0 ;p += X_T_FRAME) {
-
- TRACE("x_exists", printf("entry: %d, %d, %d, %d, %d, %d\n",
- p[0], p[1], p[2], p[3], p[4], p[5]));
-
- /* here we check address modes and continue if no good */
- if (!am_match(p[3], arg1) || !am_match(p[4], arg2)) {
- continue;
- }
- x.xlen = 0;
-
- TRACEP("x_exists", printf("entry accepted\n"));
-
- /* check up on first argument */
- if (p[1] != NONE_AM) {
- l1 = mlen(arg1);
- if (p[1] > ANY_AM) {
- /* is mode1 or mode2, and am_match will check */
- /* see note in t2.c */
- }
- else if (l1 & ~p[1]) {
- g_error(q, "argument length error");
- return NULL;
- }
- if (p[0] == 1) {
- x.xlen = (byte) l1;
- }
- }
-
- /* check up on second argument */
- if (p[2] != NONE_AM) {
- l2 = mlen(arg2);
- if (p[2] > ANY_AM) {
- if (p[2] == AS_1_AM && l1 != l2) {
- g_error(q, "length mismatch");
- return NULL;
- }
- }
- else if (l2 & ~p[2]) {
- g_error(q, "argument length error");
- return NULL;
- }
- if (p[0] == 2) {
- x.xlen = (byte) l2;
- }
- }
- return &x;
- }
- g_error(q, "opcode doesn't apply to operand combination");
- return NULL;
- }
-
- /*
- Return TRUE if loc_node is of the indicated address mode.
- */
- static bool
- am_match(register int mode, register struct node * loc)
- {
- TRACEP("am_match", printf("(mode %d, loc %p)\n", mode, loc));
-
- /* make sure loc is nonnull */
- if (loc == NULL) {
- return mode == NONE_AM;
- }
- else if (loc -> n_type != ID_TOK) {
- g_error(NULL, "internal: am_match: not a loc_node");
- return FALSE;
- }
-
- /* here, loc is guaranteed to be nonnull */
- /* WARNING: loc is a ULABEL?? (ULABELS don't even get looked up now) */
- switch (mode) {
-
- case NONE_AM: return FALSE;
- case GEN_AM: return TRUE;
- case MEM_AM: return !is_m0(loc) && !is_m1(loc);
- case ALT_AM: return !is_mpc(loc) && !is_m74(loc);
- case DALT_AM: return !is_m1(loc);
- case MALT_AM: return !is_m0(loc) && !is_m1(loc) &&
- !is_mpc(loc) && !is_m74(loc);
- case DATA_AM: return !is_m1(loc);
- case INC_AM: return is_m3(loc);
- case DEC_AM: return is_m4(loc);
- case DISP_AM: return is_m5(loc);
- case CONTROL_AM: return !is_m0(loc) && !is_m1(loc) &&
- !is_m3(loc) && !is_m4(loc) &&
- !is_m74(loc);
- case AN_AM: return is_m1(loc);
- case DN_AM: return is_m0(loc);
- case USP_AM: return 0; /* WARNING: */
-
- case IMM_AM: return is_m74(loc);
-
- /*
- WARNING: these next tests will malfunction under some
- circumstances when the local-name option is on, since they
- don't check the offset implied by the name.
-
- See x_addpsi(), resolve(), or gen_pp() for examples of how
- this is done; it involves finding the offset in the parent
- ID node. The interpretation and treatment of such offsets
- depends somewhat on the storage class. If equates are put
- in, a new storage class should be created for them.
- */
- case IMM8_AM: return is_m74(loc) && !loc -> n_cid &&
- loc -> n_const >= -128 && loc -> n_const <= 127;
- case IMM16_AM: return is_m74(loc) && !loc -> n_cid &&
- loc -> n_const >= -32768 && loc -> n_const <= 32767;
- case Q8BIT_AM: return is_m74(loc) && !loc -> n_cid &&
- loc -> n_const >= -128 && loc -> n_const <= 127;
- case QUICK8_AM: return is_m74(loc) && !loc -> n_cid &&
- loc -> n_const >= 1 && loc -> n_const <= 8;
- case BIT31_AM: return is_m74(loc) && !loc -> n_cid &&
- loc -> n_const >= 0 && loc -> n_const <= 31;
- case TRAP15_AM: return is_m74(loc) && !loc -> n_cid &&
- loc -> n_const >= 0 && loc -> n_const <= 15;
-
- /* WARNING: how do we represent a reg list??? */
- case MOVEM2R_AM:
- case MOVER2M_AM:
- case REGLIST_AM: return FALSE;
-
- case CCR_AM: return loc && loc -> n_reg1 == R_CCR;
- case SR_AM: return loc && loc -> n_reg1 == R_SR;
-
- default:
- printf("am_match: bad mode %d\n", mode);
- fatal("");
- }
- }
-
- /*
- The following 16 routines follow page 79 of the 68000 book.
-
- What they will eventually return, of course, is an index into a
- set of sub-opcode bit masks.
- */
- static bool
- is_mpc(register struct node *p)
- {
- SL_DISABLE();
- return p -> n_reg1 == R_PC;
- }
-
- static bool
- is_m0(register struct node *p)
- {
- SL_DISABLE();
- /* Data register. */
- return !(p -> n_mode) && is_dreg(p -> n_reg1) && !p -> n_reg2;
- }
-
- static bool
- is_m1(register struct node *p)
- {
- SL_DISABLE();
- /* Address register. */
- return !(p -> n_mode) && is_areg(p -> n_reg1) && !p -> n_reg2;
- }
-
- static bool
- is_m2(register struct node *p)
- {
- SL_DISABLE();
- /* Address register indirect. */
- return p -> n_mode == EA_MODE && is_areg(p -> n_reg1) &&
- !(p -> n_reg2) && !(p -> n_const);
- }
-
- static bool
- is_m3(register struct node *p)
- {
- SL_DISABLE();
- /* Address register indirect with post increment. */
- return p -> n_mode == EAPSI_MODE;
- }
-
- static bool
- is_m4(register struct node *p)
- {
- SL_DISABLE();
- /* Address register indirect with pre decrement. */
- return p -> n_mode == EAPRD_MODE;
- }
-
- static bool
- is_m5(register struct node *p)
- {
- SL_DISABLE();
- /* Address register indirect with displacement. */
- return p -> n_mode == EA_MODE &&
- is_areg(p -> n_reg1) && !(p -> n_reg2) && p -> n_const;
- }
-
- static bool
- is_m6(register struct node *p)
- {
- SL_DISABLE();
- /* Address register indirect with index. */
- return p -> n_mode == EA_MODE &&
- is_areg(p -> n_reg1) && p -> n_reg2;
- }
-
- static bool
- is_m70(register struct node *p)
- {
- SL_DISABLE();
- /* Absolute short. */
-
- /* WARNING: all abolute long for now; this will take fiddling. */
- /* note that since p is a loc_node, its C type is available, and
- the constant value is also available */
- return FALSE;
- }
-
- static bool
- is_m71(register struct node *p)
- {
- SL_DISABLE();
- /* Absolute long. */
- return !(p -> n_mode) && p -> n_cid;
- }
-
- static bool
- is_m72(register struct node *p)
- {
- SL_DISABLE();
- /* Program counter with displacement. */
- return p -> n_mode == EA_MODE &&
- p -> n_reg1 == R_PC && !(p -> n_reg2);
- }
-
- static bool
- is_m73(register struct node *p)
- {
- SL_DISABLE();
- /* Program counter with index. */
- return p -> n_mode == EA_MODE &&
- p -> n_reg1 == R_PC && p -> n_reg2;
- }
-
- static bool
- is_m74(register struct node *p)
- {
- SL_DISABLE();
- /* Immediate. */
- return !(p -> n_mode) && !(p -> n_reg1);
- }
-